package com.youpai.platform.user.service.biz.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.youpai.platform.user.service.biz.UserActiveBizService;
import com.youpai.platform.user.service.entity.dto.UserActiveDTO;
import com.youpai.platform.user.service.entity.dto.UserStateChangedDTO;
import com.youpai.platform.user.service.entity.po.UserActiveLogPO;
import com.youpai.platform.user.service.entity.po.UserActivePO;
import com.youpai.platform.user.service.entity.po.UserPO;
import com.youpai.platform.user.service.enums.UserStateEnum;
import com.youpai.platform.user.service.mapper.UserActiveLogMapper;
import com.youpai.platform.user.service.mapper.UserActiveMapper;
import com.youpai.platform.user.service.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @date: 2022/7/23 12:14
 * @author: Anna
 * @version: 1.0
 * @description: 用户状态biz实现类
 */
@Slf4j
@Component
public class UserActiveBizServiceImpl implements UserActiveBizService {

    @Resource
    private UserActiveMapper userActiveMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private UserActiveLogMapper userActiveLogMapper;

    @Override
    public void userStateChanged(UserStateChangedDTO userStateChangedDTO) {
        // 校验用户是否存在
        boolean isExist = checkUserIsExist(userStateChangedDTO.getUid());
        if (!isExist) {
            return;
        }
        // 变更用户状态
        changeUserState(userStateChangedDTO);
        // 记录用户状态变更日志
        recordUserActiveLog(userStateChangedDTO);
    }

    @Override
    public Map<Long, UserActiveDTO> queryUserActive(List<Long> uidList) {
        if (CollectionUtils.isEmpty(uidList)) {
            return new HashMap<>();
        }
        LambdaQueryWrapper<UserActivePO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(UserActivePO::getUid, uidList);
        List<UserActivePO> userActivePOList = userActiveMapper.selectList(queryWrapper);
        if (null == userActivePOList) {
            userActivePOList = new ArrayList<>(uidList.size());
        }
        Map<Long, UserActiveDTO> resultMap = new HashMap<>(uidList.size());
        for (UserActivePO userActivePO : userActivePOList) {
            resultMap.put(userActivePO.getUid(), convertUserActivePO2UserActiveDTO(userActivePO));
        }
        for (Long uid : uidList) {
            // 如果该用户从未有过状态变更，就构建默认的离线状态
            if (!resultMap.containsKey(uid)) {
                resultMap.put(uid, buildDefaultUserActiveDTO(uid));
            }
        }
        return resultMap;
    }

    private UserActiveDTO buildDefaultUserActiveDTO(Long uid) {
        UserActiveDTO userActiveDTO = new UserActiveDTO();
        userActiveDTO.setUid(uid)
                .setUserState(UserStateEnum.OFFLINE.state)
                .setUserStateTag(UserStateEnum.OFFLINE.tag);
        return userActiveDTO;
    }

    private UserActiveDTO convertUserActivePO2UserActiveDTO(UserActivePO userActivePO) {
        UserActiveDTO userActiveDTO = new UserActiveDTO();
        userActiveDTO.setUid(userActivePO.getUid())
                .setUserState(userActivePO.getUserState())
                .setUserStateTag(userActivePO.getUserStateTag());
        return userActiveDTO;
    }

    private void changeUserState(UserStateChangedDTO userStateChangedDTO) {
        UserStateEnum userStateByCode = UserStateEnum.getUserStateByCode(userStateChangedDTO.getUserState());
        // 如果是上线，则新增
        UserActivePO userActivePO = new UserActivePO()
                .setUid(userStateChangedDTO.getUid())
                .setUserState(userStateChangedDTO.getUserState())
                .setUserStateTag(userStateByCode.tag);
        try {
            userActiveMapper.insert(userActivePO);
        } catch (DuplicateKeyException duplicateKeyException) {
            LambdaUpdateWrapper<UserActivePO> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(UserActivePO::getUid, userStateChangedDTO.getUid());
            userActiveMapper.update(userActivePO, updateWrapper);
        }
    }

    private void recordUserActiveLog(UserStateChangedDTO userStateChangedDTO) {
        UserActiveLogPO userActiveLogPO = new UserActiveLogPO();
        userActiveLogPO.setReason("IM上线")
                .setUserState(userStateChangedDTO.getUserState())
                .setUserStateTag(UserStateEnum.getUserStateByCode(userStateChangedDTO.getUserState()).tag)
                .setTouchTimeStamp(userStateChangedDTO.getTimeStamp())
                .setUid(userStateChangedDTO.getUid());
        userActiveLogMapper.insert(userActiveLogPO);
    }

    private boolean checkUserIsExist(Long uid) {
        LambdaQueryWrapper<UserPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserPO::getUid, uid);
        UserPO userPO = userMapper.selectOne(queryWrapper);
        return null != userPO;
    }
}
